﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media.Media3D;
using System.Threading;
using Mogre;

namespace MultiAgents
{
    abstract public class Agent
    {
        
        
        protected Vector3 _direction; /* vector giving the direction it's going to */
        private Vector3 _position; /* Position of the center of the ogre in the map */
        private uint _distance; /*distance between the center of the ogre and the farther point it can fuck */
        protected Random _random;
        protected Program _program;
        protected bool _hunt;
        protected DateTime _nextMove;   /*remaining immobilization time (before next deplacement) after hitting for a robot; for an ogre it's the remaining time before being allowed to have a child*/

        //private uint _speed; /* unity of distance in Ogre per second */
        //private float _size; /*the ogre can be more or less big */
        
        private const int MAX_DIRECTION = 10;
        private const int MULT_FACTOR = 5;
        protected const int HUNT_PROB = 1;//probability to hunt an ogre (over 100)

        public const int MAX_DISTANCE = 1000;//10000

        public Agent() {
            }



        public Agent(Program prg, Random random, float x, float y, float z)
        {
            _random = random;
            _speed = 3;
            _direction = new Vector3(_random.Next(-MAX_DIRECTION, MAX_DIRECTION),
                _random.Next(-MAX_DIRECTION, MAX_DIRECTION),
                _random.Next(-MAX_DIRECTION, MAX_DIRECTION));
            _direction.Normalise();
            _position = new Vector3(x,y,z);
            _size = 1.0f;
            _distance = 15;
            _program = prg;
            _hunt = false;
        }

        public Vector3 getPosition()
        {
            return _position;
        }

        public void setPosition(Vector3 p)
        {
            //Question/réponse: le décor est-il infini? besoin de vérifier la cohérence de p? réponse: actuellement le décor est sphérique
            _position = p;
        }

        public void setPosition(float x, float y, float z)
        {
            setPosition(new Vector3(x, y, z));
        }

        //debug
       // public void move()
       // {      }

        public void move_random()
        {

            /*l'agent à 5% de chance de changer de direction*/
            if (_random.Next(0, 100) > 95)
            {
                _direction = new Vector3(_random.Next(-MAX_DIRECTION, MAX_DIRECTION),
                                         _random.Next(-MAX_DIRECTION, MAX_DIRECTION),
                                         _random.Next(-MAX_DIRECTION, MAX_DIRECTION));
                _direction.Normalise();
           
                //Rotation afin de regarder dans le sens du déplacement
              
            }

            /*l'agent ne doit pas sortir de l'espace ou il a le droit de se déplacer*/
            if (dist(_position + MULT_FACTOR * _direction, Vector3.ZERO) < MAX_DISTANCE)
            {
                _position += MULT_FACTOR * _direction;
            }

            /*si l'agent se dirige hors du cercle, le rediriger dans une direction convenable, le centre du cercle est une direction convenable*/
            else
            {
                Console.WriteLine("Un agent est redirigé vers le centre du cercle pour ne pas sortir de l'environnement");
                /*pour retourner dans la direction du cercle, prendre la direction opposée au vecteur position*/
                _direction = new Vector3(-_position.Normalise());

                /*vérification superflue en théorie, utile si le cercle est plus petit que le vecteur déplacement! */
                if (dist(_position + MULT_FACTOR * _direction, Vector3.ZERO) < MAX_DISTANCE)
                {
                    _position += MULT_FACTOR * _direction;
                }
                else
                    Console.WriteLine("Prbolème de possible d'environnement trop petit");
            }

        }

        /*Donne la direction à l'agent de l'ogre le plus proche (chasse pour tuer ou se reproduire!)*/
        public void hunt()
        {
            /*le segment de droite entre deux points d'un cercle est dans le cercle, donc avoir la direction suffit, pas besoin de vérifications*/
            Vector3 nextdirection = _program.directionOgre(this);
            _position += MULT_FACTOR * nextdirection;
           
        }

        public double dist(Vector3 vec, Vector3 vec2)
        {
            return System.Math.Sqrt( System.Math.Pow((vec.x - vec2.x), 2) + 
                                     System.Math.Pow((vec.y - vec2.y), 2) + 
                                     System.Math.Pow((vec.z - vec2.z), 2) );
        }

        public float getx()
        {
            return _position.x;
        }

        public float gety()
        {
            return _position.y;
        }

        public float getz()
        {
            return _position.z;
        }

        public float getdistance()
        {
            return _distance;
        }

        public Vector3 getDirection()
        {
            return _direction;
        }
    }
}
